﻿using SQLiteDB;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Utils.Common;
using Utils.Common.Enum;
using ZK.BLL.Config;
using ZK.Entity;
using ZK.Entity.Config;
using ZK.Pack;

namespace ZK.BLL.MainExecute
{
    public class GlobalExecute
    {

        private static volatile GlobalExecute instance;
        public static GlobalExecute Instance
        {
            get
            {
                if (instance == null)
                {

                    if (instance == null)
                    {
                        instance = new GlobalExecute();
                    }

                }
                return instance;
            }
        }

        public bool IsRunning = false;

        Tcp1610Printer tcpClient;
        public PrintData CurrPrintData { get; set; }
 
        public delegate void DelCompleted(PrintData printData);
        public event DelCompleted CompletedEvent;

        public Queue<SendData> queue = new Queue<SendData>();
        private object syncLocal = new object();
        BitArray bitArray;
        public int Index = 0;

    
       
        public bool Start(string logoName, string productName,string ip,int port )
        {
            try
            {
           
                
                tcpClient = new Tcp1610Printer(ip, port);
                tcpClient.Open();
                tcpClient.EventHandlerReceived += TcpClient_EventHandlerReceived; ;
                Thread.Sleep(100);

            }
            catch (Exception ex)
            {

                LogHelper.LogError(ex.Message);
                if (tcpClient != null) tcpClient.Close();
                return false;
            }
            return IsRunning = true;
        }

        private void TcpClient_EventHandlerReceived(object sender, EventArgs e)
        {

            string revStr = sender.ToString();
            Console.WriteLine(revStr);
            if (!string.IsNullOrEmpty(revStr))
            {

                lock (syncLocal)
                {
                    Index++;

                    if (bitArray != null && bitArray.Count > Index)
                    {
                        if (revStr=="NG")
                        {
                            bitArray.Set(Index, false);
                        }
                        else if (revStr == "OK")
                        {
                            bitArray.Set(Index, true);
                        }
                    }
                    if (queue.Count > 0)
                    {
                        Thread.Sleep(10);
                        var sendData = queue.Dequeue();
                        tcpClient.WriteData(sendData.Msg);
                    }
                   
                }

            }
        }

        public bool Stop()
        {
            try
            {

                tcpClient.EventHandlerReceived -= TcpClient_EventHandlerReceived;
                tcpClient.Close();
            }
            catch
            {
                return false;
            }

            IsRunning = false;
            return true;
        }

    


         

        public void ReSend(PrintData printdata )
        {

            var vdjTemplate= VDJTemplateBLL.Instance.GetByTemplateName(printdata.TemplateName.Trim());

            if (vdjTemplate == null)
            {
                LogHelper.LogError($"模板【{printdata.TemplateName.Trim()}】,请检查模板配置！");
                return;
            }
            string paramspace = "".PadLeft(SystemConfig.GetConfig().SystemInfoEntity.ParamSpace, ' ');
            List<SendData> dataList = new List<SendData>();
            dataList.Add(new SendData() { Command = printdata.TemplateName, Msg = SelectTemplate(printdata.TemplateName) });
            dataList.Add(new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName1, Msg = SendLogoData(printdata.CustomerName, SystemConfig.GetConfig().SystemInfoEntity.ParamName1) });
            dataList.Add(new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName6, Msg = SendLogoData(printdata.CustomerName2, SystemConfig.GetConfig().SystemInfoEntity.ParamName6) });

            var sendData2 = new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName2, Msg = BuildPrintData(SystemConfig.GetConfig().SystemInfoEntity.ParamName2,printdata.ProductName+ printdata.ModelNo) };
            dataList.Add(sendData2);

            var sendData3 = new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName3, Msg = BuildPrintData(SystemConfig.GetConfig().SystemInfoEntity.ParamName3, printdata.PatentNO) };
            dataList.Add(sendData3);

            var sendData4 = new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName4, Msg = BuildPrintData(SystemConfig.GetConfig().SystemInfoEntity.ParamName4, printdata.UserPrintName + printdata.BatchNo) };
            dataList.Add(sendData4);

            var sendData5 = new SendData() { Command = SystemConfig.GetConfig().SystemInfoEntity.ParamName5, Msg = BuildPrintData(SystemConfig.GetConfig().SystemInfoEntity.ParamName5, printdata.Other) };
            dataList.Add(sendData5);
            string vdjParam=  UpdateVDJParam(0, 0, vdjTemplate.CharWidth, vdjTemplate.CharHeight, vdjTemplate.CharacterGap, vdjTemplate.Delay, vdjTemplate.FontHigh);
            var sendData6 = new SendData() { Command ="VDJParam", Msg = vdjParam };
            dataList.Add(sendData6);
            WriteCommands(printdata, dataList);
        }


        //选择模板
        public string SelectTemplate(string moban)
        {
            StringBuilder stringBuilder = new StringBuilder();
            byte[] stx = new byte[] { 2 };
            byte[] etx = new byte[] { 3 };
            char type = 'M';
            stringBuilder.Append(Encoding.ASCII.GetString(stx));
            stringBuilder.Append(type);
            stringBuilder.Append(moban);
            stringBuilder.Append(Encoding.ASCII.GetString(etx));
            stringBuilder.ToString();
            return stringBuilder.ToString();

        }

        /// <summary>
        /// 图片数据
        /// </summary>
        /// <param name="imageName"></param>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public string  SendLogoData(string imageName, string paramName  )
        {
            if (string.IsNullOrEmpty(imageName))
            {
                return GetEmptyImage(paramName);
            }

            imageName = ConfigBase.LogoImg + "\\" + imageName+".bmp";
            if (!File.Exists(imageName))
            {
                LogHelper.LogError("LOGO图片不存在");
                return   GetEmptyImage(paramName) ;
            }
            using (Bitmap bmp = new Bitmap(imageName))
            {
                int width = bmp.Width;
                int height = bmp.Height;

                if (bmp.Height % 8 != 0)
                {
                    LogHelper.LogError($"图像高度:{bmp.Height},不符合通讯要求");
                    return GetEmptyImage(paramName);
                }

                int _width = width;
                int _offset = 0;
                return  GetImageStr(bmp, _width, _offset, height , paramName)  ;
            }
        }


        private string GetImageStr(Bitmap bmp, int width,int offset , int height,string paramName)
        {
 
            string str = string.Empty;
            BitArray bitArray = null;
            
            for (int x = offset; x < offset + width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    if (y % 8 == 0)
                    {
                        bitArray = new BitArray(8, false);
                    }
                    int n = y % 8;
                    Color srcColor = bmp.GetPixel(x, y);
                    byte temp = (byte)(srcColor.R * .299 + srcColor.G * .587 + srcColor.B * .114);
                    bool b = temp < 255 ? true : false;
                    bitArray.Set(7 - n, b);
                    if (n == 7)
                    {
                        int val = BitArray2Int(bitArray);
                        str += val.ToString("X2");

                    }
                }
            }
            //StringBuilder stringBuilder = new StringBuilder();
            string strdata = string.Empty;
            byte[] stx = new byte[] { 2 };
            byte[] lf = new byte[] { 10 }; //0Ah
            byte[] etx = new byte[] { 3 };
            strdata += Encoding.ASCII.GetString(stx);
            strdata += "L";
            strdata += paramName;
            // strdata += paramName + ".BMP";
            strdata += Encoding.ASCII.GetString(lf);
            strdata += height.ToString().PadLeft(2, '0');
            strdata += width.ToString().PadLeft(3, '0');
            strdata += str;
            strdata += Encoding.ASCII.GetString(etx);
            return strdata;
        }


        private string GetEmptyImage(string paramName)
        {
            // LLogo.BMP16003000000000000

            string strdata = string.Empty;
            byte[] stx = new byte[] { 2 };
            byte[] lf = new byte[] { 10 }; //0Ah
            byte[] etx = new byte[] { 3 };
            strdata += Encoding.ASCII.GetString(stx);
            strdata += "L";
            strdata += paramName;
 
            strdata += Encoding.ASCII.GetString(lf);
            strdata += "16003000000000000";
            strdata += Encoding.ASCII.GetString(etx);

            return strdata;
        }

        int BitArray2Int(BitArray ba)
        {
            int ret = 0;
            for (int i = 0; i < ba.Length; i++)
            {
                if (ba.Get(i))
                {
                    ret |= (1 << i);
                }
            }
            return ret;
        }


        public string BuildPrintData(string paramName, string msg)
        {

            StringBuilder stringBuilder = new StringBuilder(512);
            byte[] stx = new byte[] { 2 };
            byte[] etx = new byte[] { 3 };
            byte[] sep = new byte[] { 10 }; //0Ah
            char type = 'U';

            stringBuilder.Append(Encoding.ASCII.GetString(stx));
            stringBuilder.Append(type);
            stringBuilder.Append(paramName); //
            stringBuilder.Append(Encoding.ASCII.GetString(sep));
            stringBuilder.Append(msg);
            stringBuilder.Append(Encoding.ASCII.GetString(etx));
            return stringBuilder.ToString();
        }


        private string ClearString(string paramName, string space)
        {
            //清空字符串
            StringBuilder stringBuilder = new StringBuilder(512);
            byte[] stx = new byte[] { 2 };
            byte[] etx = new byte[] { 3 };
            byte[] sep = new byte[] { 10 }; //0Ah
            char type = 'U';
            stringBuilder.Append(Encoding.ASCII.GetString(stx));
            stringBuilder.Append(type);
            stringBuilder.Append(paramName); //
            stringBuilder.Append(Encoding.ASCII.GetString(sep));
            stringBuilder.Append(space);
            stringBuilder.Append(Encoding.ASCII.GetString(etx));
            stringBuilder.ToString();
            return stringBuilder.ToString();
        }
        //public string ClearImage(string paramName)
        //{
        //    //清空图片

        //    return SendLogoData(ConfigBase.Root + "\\Empty.bmp", paramName);
        //}

  
        public void WriteCommands(PrintData printData ,List<SendData> lists)
        {

            Stopwatch stopWatch = new Stopwatch();
            queue.Clear();
            lists.ForEach(s =>
            {
                queue.Enqueue(s);
            });
            stopWatch.Start();
            lock (syncLocal)
            {
                bitArray = new BitArray(lists.Count, false);
                Index = -1;

                var sendData = queue.Dequeue();
                tcpClient.WriteData(sendData.Msg);
            }

            Task.Factory.StartNew(() =>
            {
                int n = 0;
                while (n < 500 && Index < bitArray.Count - 1)
                {
                    n++;
                    Thread.Sleep(10);
                }
                bool result = true;
                lock (syncLocal)
                {
                    for (int i = 0; i < bitArray.Count; i++)
                    {
                        if (!bitArray[i])
                        {
                            result = false;
                        }
                    }
                }
                stopWatch.Stop();
                if (!result)
                {
                    LogHelper.LogError($"发送失败或超时({stopWatch.ElapsedMilliseconds}ms)");
                }
                else
                {

                    printData.Id = PrintDataBLL.Instance.GetNewID();
                    printData.PrintDate = DateTime.Now;
                    PrintDataBLL.Instance.Insert(printData);

                    LogHelper.LogDebug($"发送成功({stopWatch.ElapsedMilliseconds}ms)");
                }
            });
        }

        public void WriteCommands(  List<SendData> lists)
        {

            Stopwatch stopWatch = new Stopwatch();
            queue.Clear();
            lists.ForEach(s =>
            {
                queue.Enqueue(s);
            });
            stopWatch.Start();
            lock (syncLocal)
            {
                bitArray = new BitArray(lists.Count, false);
                Index = -1;

                var sendData = queue.Dequeue();
                tcpClient.WriteData(sendData.Msg);
            }

            Task.Factory.StartNew(() =>
            {
                int n = 0;
                while (n < 500 && Index < bitArray.Count - 1)
                {
                    n++;
                    Thread.Sleep(10);
                }
                bool result = true;
                lock (syncLocal)
                {
                    for (int i = 0; i < bitArray.Count; i++)
                    {
                        if (!bitArray[i])
                        {
                            result = false;
                        }
                    }
                }
                stopWatch.Stop();
                if (!result)
                {
                    LogHelper.LogError($"发送失败或超时({stopWatch.ElapsedMilliseconds}ms)");
                }
                else
                {
 
                    LogHelper.LogDebug($"发送成功({stopWatch.ElapsedMilliseconds}ms)");
                }
            });
        }



        public string UpdateVDJParam(  int flipIndex, int overthrowIndex, int width, int height, int charactergap, int delay, string fontHigh = "16-high")
        {
            if (IsRunning)
            {
                try
                {
                    // 翻转 0 OFF  1 ON
                    string str1 = Convert.ToString(flipIndex);
                    // 颠倒 0 OFF  1 ON
                    string str2 = Convert.ToString(overthrowIndex);

                    //0100 宽度  0001~0999
                    string str3 = string.Format("{0:D4}", width);
                    // 05 高度   01~10
                    string str4 = string.Format("{0:D2}", height);

                    //字符间隙
                    string str5 = charactergap.ToString();

                    //过期天数
                    string str6 = "00000";
                    //过期
                    string str7 = "00000";

                    //00005 延时(毫米)00000~00999
                    string str8 = string.Format("{0:D5}", delay);

                    // Raster Repeat 默认01
                    string str9 = "01";
                    //Printed drops
                    string str10 = "16";
                    //Raster substitution ON
                    string str11 = "1";
                    string str12 = "007";
                    string str13 = fontHigh;
                    //string str13 = "16-high";
                    //this.Setini("Setup", "Delay", this.AllComb[0].Text, this.iniPath);
                    //this.Setini("Setup", "Width", this.AllComb[1].Text, this.iniPath);
                    //this.Setini("Setup", "Height", this.AllComb[2].Text, this.iniPath);
                    //this.Setini("Setup", "Rev", Convert.ToString(this.AllComb[3].SelectedIndex), this.iniPath);
                    //this.Setini("Setup", "Inv", Convert.ToString(this.AllComb[4].SelectedIndex), this.iniPath);

                    char start = (char)2;
                    char end = (char)3;
                    string sendCode = start + "P" + str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8 + str9 + str10 + str11 + str12 + str13 + end;
                    if (sendCode.Length == 42)
                    {

                        //List<SendData> lists = new List<SendData>();

                        //lists.Add(new SendData() {  Command="ParamSet", Msg = sendCode });
                        //WriteCommands(lists);
                        return sendCode;
                    }

                    //发送数据
                }
                catch (Exception ex)
                {
                    LogHelper.LogError("设置参数出错:" + ex.Message);
                    return "";
                }
            }

            return "";
        }

    }
}
